﻿using BarManager.Core.BusinessRules.Interfaces.Specification;
using BarManager.Core.DomainService;
using System.Collections.Generic;

namespace BarManager.Core.BusinessRules.Specification
{
    public class EnvioAddSpecification : BaseSpecification<Entity.Envio>, IEnvioSpecification
    {        
        private IProductoRepository ProductoRepository { get; set; }
        public EnvioAddSpecification(IEnvioRepository repository, IProductoRepository productoRepository)
            : base(repository)
        {
            this.ProductoRepository = productoRepository;            
        }

        public override bool IsSatisfiedBy(Entity.Envio entity)
        {
            base.Entity = entity;

            foreach (var item in entity.Detalle)
            {
                if (item is Entity.EnvioDetalleProducto)
                {
                    int stockActual = 0;
                    var aux = item as Entity.EnvioDetalleProducto;

                    if (!TieneStockSuficiente(aux.Producto, item.Cantidad, out stockActual)) return false;                   
                }

                //- Validamos promociones
                if (item is Entity.EnvioDetallePromocion)
                {
                    foreach (var promo in (item as Entity.EnvioDetallePromocion).Promocion.PromocionDetalleList)
                    {
                        int stockActual = 0;
                        if (!TieneStockSuficiente(promo.Producto, item.Cantidad * promo.Cantidad, out stockActual)) return false;
                    }
                }
            }
            return true;
        }

        public override IEnumerable<string> GetErrorMessage()
        {
            foreach (var item in Entity.Detalle)
            {
                //- Validamos productos
                if (item is Entity.EnvioDetalleProducto)
                {
                    int stockActual = 0;
                    var aux = item as Entity.EnvioDetalleProducto;

                    if (!TieneStockSuficiente(aux.Producto, item.Cantidad, out stockActual)) 
                        yield return string.Format("El producto {0} tiene un stock actual de {1} items e intena agregar {2} items.", aux.Producto.Nombre, stockActual, item.Cantidad);
                }

                //- Validamos promociones
                if (item is Entity.EnvioDetallePromocion)
                {
                    foreach (var promo in (item as Entity.EnvioDetallePromocion).Promocion.PromocionDetalleList)
                    {
                        int stockActual = 0;
                        if (!TieneStockSuficiente(promo.Producto, item.Cantidad * promo.Cantidad, out stockActual))
                            yield return string.Format("La promocion {0} no tiene stock para el producto {1}.", promo.Promocion.Descripcion, promo.Producto.Nombre);
                    }
                }
            }
            yield break;
        }        

        private bool TieneStockSuficiente(Entity.Producto producto, int cantADescontar, out int stockActual)
        {
            stockActual = 0;
            var prod = ProductoRepository.Get(x => x.Id == producto.Id);

            //- Si no existe producto sale
            if (prod == null) return false;

            //- Si no controla stock sale
            if (!prod.ControlarStock) return true;

            //- Devolemos stock actual y si es suficiente para el pedido
            stockActual = prod.Stock.Value;
            return (prod.Stock >= cantADescontar);
        }
    }
}
